package com.gcxy.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gcxy.constant.StringConst;
import com.gcxy.core.R;
import com.gcxy.dto.resources.AddResourceDTO;
import com.gcxy.dto.resources.ResourcePageDTO;
import com.gcxy.dto.resources.UpdateResourceDTO;
import com.gcxy.entity.Resource;
import com.gcxy.entity.ResourceRole;
import com.gcxy.entity.Role;
import com.gcxy.mapper.ResourceMapper;
import com.gcxy.mapper.ResourceRoleMapper;
import com.gcxy.service.ResourceService;
import com.gcxy.utils.BeanCopyUtil;
import com.gcxy.vo.resource.ResourceVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author pep7chiao
 * @since 2022-09-27
 */
@Service
public class ResourceServiceImpl extends ServiceImpl<ResourceMapper, Resource> implements ResourceService {
    @Autowired
    private ResourceMapper resourceMapper;
    @Autowired
    private ResourceRoleMapper resourceRoleMapper;

    /**
     * 获取所有封装好的资源权限
     *
     * @return 已封装的资源权限
     */
    @Override
    public List<ResourceVO> getResourceList() {
        List<Resource> resourceList = resourceMapper.selectList(null);
        // 获取所有资源权限
        List<ResourceVO> resourceVOList = BeanCopyUtil.copyList(resourceList, ResourceVO.class);
        // 递归封装子权限并返回
        return setResourceChildren(resourceVOList, 0);
    }

    /**
     * 根据角色ID获取对应的资源权限（资源树）
     *
     * @param roleId 角色ID
     * @return 角色对应的资源权限ID集合
     */
    @Override
    public List<ResourceVO> getResourceByRoleId(Integer roleId) {
        List<Resource> resourceList = resourceMapper.getResourceByRoleId(roleId);
        // 获取所有资源权限
        List<ResourceVO> resources = BeanCopyUtil.copyList(resourceList, ResourceVO.class);
        // 递归封装子权限并返回
        return setResourceChildren(resources, 0);
    }

    /**
     * 根据角色ID获取对应的资源权限（资源列表）
     *
     * @param roleId 角色ID
     * @return 角色对应的资源权限ID集合
     */
    @Override
    public List<ResourceVO> getResourceListByRoleId(Integer roleId) {
        List<Resource> resourceList = resourceMapper.getResourceByRoleId(roleId);
        // 获取所有资源权限
        return BeanCopyUtil.copyList(resourceList, ResourceVO.class);
    }


    /**
     * 根据条件查询资源
     *
     * @param resourcePageDTO 查询条件对象
     * @return 资源结果对象
     */
    @Override
    public List<ResourceVO> getResourceByCondition(ResourcePageDTO resourcePageDTO) {
        String resourceName = resourcePageDTO.getResourceName();
        String resourcePath = resourcePageDTO.getResourcePath();
        Integer resourceType = resourcePageDTO.getResourceType();
        Integer parentId = resourcePageDTO.getParentId();
        LambdaQueryWrapper<Resource> query = new LambdaQueryWrapper();
        query.like(!ObjectUtils.isEmpty(resourceName), Resource::getResourceName, resourceName)
                .like(!ObjectUtils.isEmpty(resourcePath), Resource::getResourcePath, resourcePath)
                .eq(!ObjectUtils.isEmpty(resourceType), Resource::getResourcePath, resourcePath)
                .eq(!ObjectUtils.isEmpty(parentId), Resource::getResourcePath, resourcePath);
        // 获取资源权限
        List<Resource> resourcesList = resourceMapper.selectList(query);
        List<ResourceVO> resourceVOList = BeanCopyUtil.copyList(resourcesList, ResourceVO.class);
        // 递归封装子权限并返回
        return setResourceChildren(resourceVOList, 0);
    }

    /**
     * 更新资源
     *
     * @param updateResourceDTO 更新的资源数据对象
     * @return 更新结果
     */
    @Override
    public R<?> UpdateResource(UpdateResourceDTO updateResourceDTO) {
        Integer resourceId = updateResourceDTO.getId();
        //查看要更新的资源是否存在
        Resource resource = resourceMapper.selectById(resourceId);
        if (ObjectUtils.isEmpty(resource)) {
            return R.Failed("该资源不存在！");
        }
        String resourceName = updateResourceDTO.getResourceName();
        String resourcePath = updateResourceDTO.getResourcePath();
        LambdaQueryWrapper<Resource> queryName = new LambdaQueryWrapper();
        queryName.eq(!ObjectUtils.isEmpty(resourceName), Resource::getResourceName, resourceName);
        List<Resource> resourceNameList = resourceMapper.selectList(queryName);
        if (!ObjectUtils.isEmpty(resourceNameList) && resourceNameList.size() > 1) {
            return R.Failed("操作失败，资源名字重复！");
        }
        LambdaQueryWrapper<Resource> queryPath = new LambdaQueryWrapper();
        queryPath.eq(!ObjectUtils.isEmpty(resourcePath), Resource::getResourcePath, resourcePath);
        List<Resource> resourcePathList = resourceMapper.selectList(queryPath);
        if (!ObjectUtils.isEmpty(resourcePathList) && resourceNameList.size() > 1) {
            return R.Failed("操作失败，资源路径重复！");
        }
        resource = BeanCopyUtil.copy(updateResourceDTO, Resource.class);
        resourceMapper.updateById(resource);
        return R.Success("修改成功！");
    }

    /**
     * 新增资源
     *
     * @param addResourceDTO 新增的资源数据对象
     * @return 新增结果
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public R<Void> insertResource(AddResourceDTO addResourceDTO) {
        String resourceName = addResourceDTO.getResourceName();
        String resourcePath = addResourceDTO.getResourcePath();
        R<Void> res = verifyDuplicates(resourceName, resourcePath);
        if (res != null) return res;
        Resource resource = BeanCopyUtil.copy(addResourceDTO, Resource.class);
        int row = resourceMapper.insert(resource);
        if (row > 0) {
            ResourceRole resourceRole = new ResourceRole();
            resourceRole.setRoleId(StringConst.SUPER_ADMIN);
            resourceRole.setResourceId(resource.getId());
            resourceRoleMapper.insert(resourceRole);
            return R.Success("添加成功！", resource.getId());
        }
        return R.Failed("添加失败！");
    }

    /**
     * 查重资源名称和资源路径
     *
     * @param resourceName 查重的资源名称
     * @param resourcePath 查重的资源路径
     * @return 查重结果
     */
    private R<Void> verifyDuplicates(String resourceName, String resourcePath) {
        LambdaQueryWrapper<Resource> queryName = new LambdaQueryWrapper();
        queryName.eq(!ObjectUtils.isEmpty(resourceName), Resource::getResourceName, resourceName);
        Resource repeatedNameResource = resourceMapper.selectOne(queryName);
        if (!ObjectUtils.isEmpty(repeatedNameResource)) {
            return R.Failed("操作失败，资源名字重复！");
        }
        LambdaQueryWrapper<Resource> queryPath = new LambdaQueryWrapper();
        queryPath.eq(!ObjectUtils.isEmpty(resourcePath), Resource::getResourcePath, resourcePath);
        Resource repeatedPathResource = resourceMapper.selectOne(queryPath);
        if (!ObjectUtils.isEmpty(repeatedPathResource)) {
            return R.Failed("操作失败，资源路径重复！");
        }
        return null;
    }

    /**
     * 更加ID删除资源
     *
     * @param id 要删除的资源id
     * @return 删除结果
     */
    @Override
    public R<?> deleteResourceById(Integer id) {
        List<Role> roleList = resourceRoleMapper.selectRoleByResourceId(id);
        List<Role> filterRoleList = roleList.stream().filter(role -> role.getId() != StringConst.SUPER_ADMIN).collect(Collectors.toList());
        if (filterRoleList != null && filterRoleList.size() > 0) {
            return R.Failed("删除失败，有关联角色！", roleList);
        }
        resourceMapper.deleteById(id);
        return R.Success("删除成功！");
    }

    /**
     * 获取封装好的资源权限集合（递归）
     *
     * @param resources 所有资源权限数据
     * @param parentId  父ID
     * @return 封装好的资源权限集合
     */
    private List<ResourceVO> setResourceChildren(List<ResourceVO> resources, Integer parentId) {
        // 存储资源权限的集合
        List<ResourceVO> children = new ArrayList<>();
        // 遍历所有权限集合
        for (ResourceVO resource : resources) {
            // 如果当前集合中的父ID与传来的父ID相同
            if (resource.getParentId().equals(parentId)) {
                children.add(resource);
            }
        }
        // 递归获取并设置所有子权限
        for (ResourceVO child : children) {
            child.setChildren(setResourceChildren(resources, child.getId()));
        }
        // 如果没有子权限则返回一个空集合
        if (children.size() == 0) {
            return null;
        }
        return children;
    }


}
